package cn.lopr.im.api.service.impl;

import cn.lopr.im.api.annotation.DataSource;
import cn.lopr.im.api.bean.*;
import cn.lopr.im.api.configuration.datasources.DynamicDataSourceEnum;
import cn.lopr.im.api.service.IArticleService;
import cn.lopr.im.api.service.ICommunityDBService;
import cn.lopr.im.api.service.IUserService;
import cn.lopr.im.api.utils.DateUtil;
import cn.lopr.im.api.utils.IdWorker;
import cn.lopr.im.api.vo.ArticleCommentVo;
import cn.lopr.im.api.vo.ArticleVo;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
 * @author shuangyang7
 * @date 2021/5/19 22:15
 */
@Service
public class ArticleServiceImpl implements IArticleService {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private IUserService userService;

    @Autowired
    private ICommunityDBService communityDBService;


    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public List<ArticlePlate> getPlate() {
        return communityDBService.selectPlate();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public PageInfo<ArticleVo> getArticleList(User user, int page, int size, String plateID) {
        PageInfo<Article> articles = communityDBService.selectArticleByPageAndPlateID(plateID, page, size);

        List<ArticleVo> articleVosPage = new ArrayList<>();
        PageInfo<ArticleVo> articleVoPageInfo = new PageInfo<>();

        setPageInfo(user, articles, articleVosPage, articleVoPageInfo);

        return articleVoPageInfo;
    }

    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public PageInfo<ArticleVo> getArticleListByUserId(User user, int page, int size, String userId) {
        PageInfo<Article> articles = communityDBService.selectArticleByPageAndUserId(userId, page, size);

        List<ArticleVo> articleVosPage = new ArrayList<>();
        PageInfo<ArticleVo> articleVoPageInfo = new PageInfo<>();
        setPageInfo(user, articles, articleVosPage, articleVoPageInfo);

        return articleVoPageInfo;
    }

    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public ArticleVo getArticle(User user, String articleId) {

        List<ArticleOption> articleOptions = communityDBService.selectArticleOptionByRecord(
                new ArticleOption().setUserId(user.getId()).setArticleId(articleId)
                        .setOptionType(Option.OptionType.VISIT.getCode()).setIsDelete(false));
        //如果没有浏览过，就增加一条浏览记录
        if (articleOptions.size() == 0) {
            ArticleOption articleOption = new ArticleOption();
            articleOption.setId(idWorker.nextId() + "");
            articleOption.setUserId(user.getId());
            articleOption.setOptionType(Option.OptionType.VISIT.getCode());
            articleOption.setArticleId(articleId);
            communityDBService.addArticleOption(articleOption);
            Article article = new Article();
            article.setVisits(1);
            article.setId(articleId);
            communityDBService.updateArticleByRecord(article);
        }

        Article article = new Article();
        article.setId(articleId);

        List<Article> articles = communityDBService.selectArticleByRecord(article);
        if (articles.size() == 0) {
            return new ArticleVo();
        }

        return getArticleVo(user, articles.get(0));
    }

    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public boolean addArticle(User user, Article article) {
        article.setId(idWorker.nextId() + "");
        article.setPublishUserId(user.getId());
        article.setPublishTime(DateUtil.getTimeIsDateType());
        int i = communityDBService.addArticleByRecord(article);
        return i != 0;
    }

    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public boolean updateArticle(User user, Article article) {

        if (!StringUtils.isEmpty(article.getContent())) {
            article.setPublishUserId(user.getId());
            return communityDBService.updateArticleByRecord(article) != 0;
        }

        ArticleOption articleOption = new ArticleOption();
        articleOption.setId(idWorker.nextId() + "");
        articleOption.setArticleId(article.getId());
        articleOption.setUserId(user.getId());

        if (article.getLike() != null) {
            List<ArticleOption> articleOptions = communityDBService.selectArticleOptionByRecord(
                    new ArticleOption().setUserId(user.getId()).setArticleId(article.getId())
                            .setOptionType(Option.OptionType.LIKE.getCode()).setIsDelete(false));
            if (articleOptions.size() == 0) {
                articleOption.setOptionType(Option.OptionType.LIKE.getCode());
                communityDBService.addArticleOption(articleOption);
                int i = communityDBService.updateArticleByRecord(article);
            } else {
                ArticleOption articleOptionDel = articleOptions.get(0);
                communityDBService.updateArticleOptionByRecord(articleOptionDel.setIsDelete(true));
                article.setLike(-1);
                communityDBService.updateArticleByRecord(article);
            }
        }

        if (article.getVisits() != null) {
            List<ArticleOption> articleOptions = communityDBService.selectArticleOptionByRecord(
                    new ArticleOption().setUserId(user.getId()).setArticleId(article.getId())
                            .setOptionType(Option.OptionType.VISIT.getCode()).setIsDelete(false));
            if (articleOptions.size() == 0) {
                articleOption.setOptionType(Option.OptionType.VISIT.getCode());
                communityDBService.addArticleOption(articleOption);
                communityDBService.updateArticleByRecord(article);
                int i = communityDBService.updateArticleByRecord(article);
            }
        }

        return true;
    }

    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public boolean delArticle(User user, String articleId) {
        Article dbWhere = new Article();
        dbWhere.setPublishUserId(user.getId());
        dbWhere.setId(articleId);

        if (communityDBService.selectArticleByRecord(dbWhere).size() == 0) {
            return false;
        }
        dbWhere.setPublishUserId(null);
        dbWhere.setIsDelete(true);

        return communityDBService.updateArticleByRecord(dbWhere) != 0;
    }

    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public ArrayList<ArticleCommentVo> getArticleComment(String articleId, int page, int size) {

        List<ArticleComment> articleComments = communityDBService.selectArticleCommentByArticleIdAndPage(articleId, page - 1, size);

        ArrayList<ArticleCommentVo> articleCommentVos = new ArrayList<>();

        for (ArticleComment comment : articleComments) {
            User userById = userService.getUserById(comment.getUserId());
            ArticleCommentVo articleCommentVo = new ArticleCommentVo(comment);
            articleCommentVo.setCurrentUser(userById);

            List<ArticleComment> childArticleComments = communityDBService.selectArticleCommentByCommentParentId(comment.getId(), page - 1, 2);
            ArrayList<ArticleCommentVo> childArticleCommentVos = new ArrayList<>();
            for (ArticleComment childArticleComment : childArticleComments) {
                User childUserById = userService.getUserById(childArticleComment.getUserId());
                ArticleCommentVo childArticleCommentVo = new ArticleCommentVo(childArticleComment);
                childArticleCommentVo.setCurrentUser(childUserById);
                childArticleCommentVos.add(childArticleCommentVo);
            }

            articleCommentVo.setChildArticleCommentVos(childArticleCommentVos);
            articleCommentVo.setChildArticleCommentTotal(communityDBService.countArticleCommentByParentId(comment.getId()));
            articleCommentVos.add(articleCommentVo);
        }

        return articleCommentVos;
    }


    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public List<ArticleCommentVo> getArticleChildCommentMultistage(String parentId, int page, int size) {
        ArticleComment articleCommentDbWhere = new ArticleComment();
        articleCommentDbWhere.setId(parentId);
        List<ArticleComment> articleComments = communityDBService.selectArticleCommentBySelective(articleCommentDbWhere);
        if (articleComments.size() == 0) {
            return null;
        }

        ArticleComment articleComment = articleComments.get(0);

        ArticleCommentVo articleCommentVo = new ArticleCommentVo(articleComment);
        User userById = userService.getUserById(articleComment.getUserId());
        articleCommentVo.setCurrentUser(userById);

        ArrayList<ArticleCommentVo> articleCommentVos = new ArrayList<>();
        articleCommentVos.add(articleCommentVo);

        return getSons(articleCommentVos);
    }

    @Override
    public List<ArticleCommentVo> getArticleChildCommentSingle(String parentId, int page, int size) {
        ArticleComment articleCommentDbWhere = new ArticleComment();
        articleCommentDbWhere.setId(parentId);
        List<ArticleComment> articleComments = communityDBService.selectArticleCommentBySelective(articleCommentDbWhere);

        if (articleComments.size() == 0) {
            return null;
        }

        ArticleComment articleComment = articleComments.get(0);
        articleCommentDbWhere = new ArticleComment();
        articleCommentDbWhere.setParentId(articleComment.getParentId());
        List<ArticleComment> articleComments1 = communityDBService.selectArticleCommentBySelective(articleCommentDbWhere);

        List<ArticleCommentVo> articleCommentVos = new ArrayList<>();

        for (ArticleComment comment : articleComments1) {

        }

        return null;
    }

    //获取子评论
    private List<ArticleCommentVo> getSons(List<ArticleCommentVo> parentComments) {
        if (parentComments == null || parentComments.size() == 0) {
            return null;
        }
        for (ArticleCommentVo parentComment : parentComments) {

            ArticleComment articleCommentDbWhere = new ArticleComment();
            articleCommentDbWhere.setParentId(parentComment.getId());
            List<ArticleComment> sonComments = communityDBService.selectArticleCommentBySelective(articleCommentDbWhere);

            ArrayList<ArticleCommentVo> childArticleCommentVos = new ArrayList<>();

            for (ArticleComment sonComment : sonComments) {
                User childUserById = userService.getUserById(sonComment.getUserId());
                ArticleCommentVo childArticleCommentVo = new ArticleCommentVo(sonComment);
                childArticleCommentVo.setCurrentUser(childUserById);
                childArticleCommentVos.add(childArticleCommentVo);
            }
            parentComment.setChildArticleCommentVos(getSons(childArticleCommentVos));
        }
        return parentComments;
    }

    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public boolean addArticleComment(User user, ArticleComment articleComment) {
        articleComment.setId(idWorker.nextId() + "");
        articleComment.setUserId(user.getId());
        if (communityDBService.addArticleCommentBySelective(articleComment) == 0) {
            return false;
        }
        Article article = new Article();
        article.setId(articleComment.getArticleId());
        article.setComment(1);
        communityDBService.updateArticleByRecord(article);
        ArticleOption articleOption = new ArticleOption().setArticleId(article.getId()).setUserId(user.getId())
                .setOptionType(Option.OptionType.COMMENT.getCode())
                .setIsDelete(false).setId(idWorker.nextId() + "");

        communityDBService.addArticleOption(articleOption);
        return true;
    }

    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public List<ArticleOption> getArticleLike(String articleID) {
        return null;
    }

    @Override
    @DataSource(DynamicDataSourceEnum.COMMUNITY)
    public List<ArticleOption> getArticleShare(String articleID) {
        return null;
    }


    private ArticleVo getArticleVo(User user, Article article) {
        User userById = userService.getUserById(article.getPublishUserId());

        List<ArticleOption> articleOptions = communityDBService.selectArticleOptionByRecord(
                new ArticleOption().setArticleId(article.getId()).setUserId(user.getId()).setIsDelete(false));

        Stream<ArticleOption> articleOptionsVisit = articleOptions.stream().filter(articleOption -> articleOption.getOptionType() == Option.OptionType.VISIT.getCode());
        Stream<ArticleOption> articleOptionsLike = articleOptions.stream().filter(articleOption -> articleOption.getOptionType() == Option.OptionType.LIKE.getCode());
        Stream<ArticleOption> articleOptionsComment = articleOptions.stream().filter(articleOption -> articleOption.getOptionType() == Option.OptionType.COMMENT.getCode());

        return new ArticleVo(article)
                .setUserID(userById.getId()).setPhone(userById.getPhone())
                .setNickname(userById.getNickname()).setSex(userById.getSex())
                .setBirthday(userById.getBirthday()).setPortrait(userById.getPortrait())
                .setIntroduction(userById.getIntroduction()).setSelf(userById.getId().equals(user.getId()))
                .setSelfLike(articleOptionsLike.count() != 0)
                .setSelfVisit(articleOptionsVisit.count() != 0)
                .setSelfComment(articleOptionsComment.count() != 0);
    }

    private void setPageInfo(User user, PageInfo<Article> articles, List<ArticleVo> articleVosPage, PageInfo<ArticleVo> articleVoPageInfo) {
        for (Article article : articles.getList()) {
            ArticleVo articleVo = getArticleVo(user, article);
            articleVosPage.add(articleVo);
        }
        articleVoPageInfo.setList(articleVosPage);
        articleVoPageInfo.setPageNum(articles.getPageNum());
        articleVoPageInfo.setPageSize(articles.getPageSize());
        articleVoPageInfo.setStartRow(articles.getStartRow());
        articleVoPageInfo.setEndRow(articles.getEndRow());
        articleVoPageInfo.setTotal(articles.getTotal());
        articleVoPageInfo.setPages(articles.getPages());
        articleVoPageInfo.setIsFirstPage(articles.isIsFirstPage());
        articleVoPageInfo.setIsLastPage(articles.isIsLastPage());
    }

}
